package org.projecteboot.reptile.common.pageprocessor;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.projecteboot.compent.core.utils.JsonUtil;
import org.projecteboot.compent.core.utils.MapUtil;
import org.projecteboot.compent.core.utils.UrlUtil;
import org.projecteboot.reptile.common.entity.ReptilePage;
import org.projecteboot.reptile.common.entity.ReptilePageRule;
import org.projecteboot.reptile.common.entity.ReptileRule;
import org.projecteboot.reptile.common.mapper.ExtReptilePageRuleMapper;
import org.projecteboot.reptile.common.mapper.ReptilePageRuleMapper;
import org.projecteboot.reptile.common.mapper.ReptileRuleMapper;
import org.projecteboot.reptile.common.service.ReptileLogService;
import org.projecteboot.reptile.common.service.ReptilePageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.selector.Html;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author LuoQiang
 * @date 2019/8/30 12:31
 **/
@Slf4j
@Service
public class CommonPageProcessor implements PageProcessor {
    @Autowired
    private ReptilePageService reptilePageService;
    @Autowired
    private ReptileLogService reptileLogService;
    @Resource
    private ReptilePageRuleMapper reptilePageRuleMapper;
    @Resource
    private ExtReptilePageRuleMapper extReptilePageRuleMapper;
    @Resource
    private ReptileRuleMapper reptileRuleMapper;

    @Override
    public void process(Page page) {
        ReptilePage reptilePage = reptilePageService.findByPage(page);
        if (reptilePage == null) {
            reptileLogService.warn("页面{}无法解析", page.getRequest().getUrl());
            return;
        }
        Long pageRuleId = reptilePage.getPageRuleId();
        ReptilePageRule reptilePageRule = reptilePageRuleMapper.selectById(pageRuleId);

        List<ReptilePageRule> reptilePageRules = new ArrayList<>();
        if (reptilePageRule.getGroupId() == 0) {
            List<ReptilePageRule> reptilePageRuleList = extReptilePageRuleMapper.listByGroupId(reptilePageRule.getId());
            if (CollectionUtils.isNotEmpty(reptilePageRuleList)) {
                reptilePageRuleList.forEach(rule -> {
                    if (StringUtils.isNotBlank(rule.getPattern())) {
                        if (checkPageRule(reptilePage, rule)) {
                            reptilePageRules.add(rule);
                        } else {
                            reptileLogService.warn("页面规则:{}无法匹配页面:{}", rule, reptilePage);
                        }
                    }
                });
            }
        } else {
            if (StringUtils.isNotBlank(reptilePageRule.getPattern())) {
                if (checkPageRule(reptilePage, reptilePageRule)) {
                    reptilePageRules.add(reptilePageRule);
                } else {
                    reptileLogService.warn("页面规则:{}无法匹配页面:{}", reptilePageRule, reptilePage);
                }
            }
        }
        Html html = page.getHtml();
        for (ReptilePageRule pageRule : reptilePageRules) {
            //拉取页面
            Long linkRuleId = pageRule.getLinkRuleId();
            if (linkRuleId == null) {
                log.info("ReptilePageRule.linkRuleId为空,{}", pageRule);
            } else {
                ReptileRule reptileRule = reptileRuleMapper.selectById(linkRuleId);
                String linkPatternStr = reptileRule.getPattern();
                Map<String, Object> linkPatternMap = JsonUtil.str2Obj(linkPatternStr, Map.class);
                String regexPattern = MapUtil.getMapValue(linkPatternMap, "regex");
                List<String> links = html.links().regex(regexPattern).all();
                links.forEach(link -> {
                    ReptilePage linkReptilePage = reptilePageService.findByUrlAndPageRuleId(link, pageRuleId);
                    if (linkReptilePage == null) {
                        Matcher matcher = Pattern.compile("([a-zA-Z]+://)?([a-zA-Z0-9/\\._]+)").matcher(link);
                        if (matcher.matches()) {
                            linkReptilePage = new ReptilePage();
                            linkReptilePage.setParentId(reptilePage.getId());
                            linkReptilePage.setSource("SYS");
                            linkReptilePage.setProtocol(matcher.group(2));
                            linkReptilePage.setUrl(matcher.group(3));
                            linkReptilePage.setUrlHash(UrlUtil.urlHash(linkReptilePage.getUrl()));
                            linkReptilePage.setSucess("NO");
                            linkReptilePage.setPageRuleId(pageRuleId);
                            linkReptilePage.setRetryTimes(0);
                            reptilePageService.save(linkReptilePage);
                        }

                    }
                });
            }

        }

    }

    private boolean checkPageRule(ReptilePage reptilePage, ReptilePageRule reptilePageRule) {
        String url = reptilePage.getUrl();
        String patternStr = reptilePageRule.getPattern();
        Map<String, Object> patternMap = JsonUtil.str2Obj(patternStr, Map.class);
        String urlPattern = MapUtil.getMapValue(patternMap, "url");
        Pattern pattern = Pattern.compile(urlPattern);
        Matcher matcher = pattern.matcher(url);
        boolean matches = matcher.matches();
        return matches;
    }

    @Override
    public Site getSite() {
        return Site.me().setRetryTimes(10000).setSleepTime(5000).setTimeOut(100000);
    }

    public static void main(String[] args) {
        String a = "m\\.235zw\\.com/19/19028/";
        Matcher matcher = Pattern.compile("a").matcher("https://m.235zw.com/19/19028/");
        if (matcher.matches()) {
            for (int i = 0; i <= matcher.groupCount(); i++) {
                System.out.println(i + "   " + matcher.group(i));
            }
        }
    }
}
